#include "MsnTransport.h"
#include "MsnConnection.h"
#include "Util.h"

MsnTransport::MsnTransport():wxThread(wxTHREAD_JOINABLE)
{
	connected = false;
	closed = false;
	socket = NULL;
}

MsnTransport::~MsnTransport()
{
	//DEBUG(_T("~MsnTransport"));
	
}

void MsnTransport::SetConnection(MsnConnection* conn)
{
	connection = conn;
}

void MsnTransport::Start()
{
     if((this->Create() == wxTHREAD_NO_ERROR )){
          if(this->Run() != wxTHREAD_NO_ERROR){
              WARN(_("start thread error"));
          }
     }else{
         WARN(_("start thread error"));
     }
}

void MsnTransport::OnExit()
{
	wxDELETE(socket);
}


bool MsnTransport::Open()
{
	DEBUG(_T("open transport to: ")+ serverAddress + _T(":")+wxString::Format(_T("%d"), serverPort));

	if(socket){
        socket->Close();
		wxDELETE(socket);
    }

	socket = new wxSocketClient();

    socket->SetFlags(wxSOCKET_WAITALL | wxSOCKET_BLOCK );

    wxIPV4address addr;
    addr.Hostname(serverAddress);
    addr.Service(serverPort);

    ((wxSocketClient*)socket)->Connect(addr, true);
    //socket->WaitOnConnect(10);

    if (socket->IsConnected()){
		connection->ConnectionOpened();
		return true;
	}else{
		DEBUG(_T("failed to connect to: ") + serverAddress + _T(":") + wxString::Format(_T("%d"), serverPort));
		connection->ConnectionFailed();
		return false;
	}

	return true;
}

void MsnTransport::Close()
{
    closed = true;
    if(socket){
        socket->Close();
    }
}

void MsnTransport::CloseAndDelete()
{
    Close();
    Delete();
	//Wait();
}

bool MsnTransport::IsConnected()
{
	return connected && !closed;
}

wxString MsnTransport::ReadLine()
{
    wxMemoryBuffer buf;
    char c;
    while(true){
        socket->Read(&c,1);
        if(c == 13)
            continue;
        if(c == 10)
            break;

        if(socket == NULL || socket->Error()){
           break;
        }

       buf.AppendByte(c);
    }

    return wxString((char*)buf.GetData(), wxConvUTF8, buf.GetDataLen());
}

void MsnTransport::ReadChunk(char* buf, int len)
{
    unsigned int read = 0;
    while(read < len){
        socket->Read(buf+read, len-read);

        if(socket->Error()){
           break;
        }

        int n = socket->LastCount();
        read += n;

        //wxString log;
        //log<<_T("read ")<<read<<_T(" bytes");
    }	
}

void MsnTransport::ReadData(wxMemoryBuffer& mb, int len)
{
	char* buf = new char[len];

	ReadChunk(buf, len);

	mb.AppendData(buf, len);

	delete[] buf;
}

wxString MsnTransport::ReadChunk(int len)
{
    char* c = new char[len+1];
    int read = 0;
    while(read<len){
        socket->Read(c+read,len-read);

        if(socket->Error()){
           break;
        }

        int n = socket->LastCount();
        read += n;
    }
    c[len] = 0;

    wxString result = wxString(c, wxConvUTF8,len);
    delete[] c;
    return result;
}

void MsnTransport::SendData(const wxString& str)
{
	SendData(WS2C(str),WSLEN(str));
}



